const mosca = require('mosca');
const task=require('../task');
const schedule = require("node-schedule");
module.exports = function() {
    let Server;
    let taskItems={};
    let jobs={};
    let baseKey="Task:Client:";
    let redisClient=global.Redis.getClient();
    let start =async function(){
       await loadTaskItems();
        let setting = {
            port: global.Config.task.port,
            maxInflightMessages: 10240, //设置单条消息的最大长度，超出后服务端会返回
            http: { //websocket 配置
                port: global.Config.task.webSocket.port,
                bundle: global.Config.task.webSocket.bundle, //提供mqtt.js
                static: global.Config.task.webSocket.static
            },
            backend: {
                type: 'redis',
                redis: require('redis'),
                db: global.Config.redis.db,
                port: global.Config.redis.port,
                return_buffers: true, // to handle binary payloads
                host: global.Config.redis.host,
                password: global.Config.redis.password,
                //指定数据保留多长时间，单位毫秒
                ttl: {
                    // TTL for subscriptions is 23 hour
                    subscriptions: 23 * 60 * 60 * 1000,
                    // TTL for packets is 23 hour
                    packets: 23 * 60 * 60 * 1000,
                }
            },
            // backend:{//直接代理emqtt
            //     type: 'mqtt',
            //     json: false,
            //     mqtt: require('mqtt'),
            //     url: 'mqtt://127.0.0.1:1883'
            // },
            persistence: { //数据持久化
                factory: mosca.persistence.Redis,
                host: global.Config.redis.host,
                port: global.Config.redis.port,
                db: global.Config.redis.db,
                return_buffers: true,
                password: global.Config.redis.password,
                ttl: {
                    // TTL for subscriptions is 23 hour
                    subscriptions: 23 * 60 * 60 * 1000,
                    // TTL for packets is 23 hour
                    packets: 23 * 60 * 60 * 1000
                }
            }
        };

        Server = new mosca.Server(setting);

        Server.on('ready', function() {
            log.info('Task Server is running...,port is ' + setting.port);
            task.start();
        });

        Server.on('clientConnected', function(client) {
            console.log('client connected', client.id);
            if(taskItems[client.id]){
                taskItems[client.id].isOnline=true;
                redisClient.hset(client.id,"isOnline",1);
            }
            publish("Task:Monitor:TaskState",0,{
               clientId: client.id,
                isOnline:true
            });

        });

        Server.on('clientDisconnected', function(client) {
             console.log('Client Disconnected:', client.id);
            if(taskItems[client.id]){
                taskItems[client.id].isOnline=false;
                redisClient.hset(client.id,'isOnline',0);
            }
            publish("Task:Monitor:TaskState",0,{
                clientId: client.id,
                isOnline:false
            });
        });

        Server.on('error', function(err) {
            console.log('Client Disconnected:', err);
        });

        /**
         * 监听MQTT主题消息
         **/
        Server.on('published', (packet, client)=> {
            this.onReciveMsg(packet, client);
        });

        return Server;
    };

    /**
     * 加载任务
     * @returns {Promise<void>}
     */
    let loadTaskItems=async function(){
        if(jobs.length>0){
            for(let clientId in jobs){
                if(jobs[clientId]){
                    jobs[clientId].cancel();
                }
            }
        }
      let keys=await redisClient.keys(baseKey+"*");
        for(let i=0;i<keys.length;i++){
            let clientInfo=await redisClient.hgetall(keys[i]);
            if(clientInfo.isAuto==="true"){//自动模式
                taskItems[clientInfo.clientId]=clientInfo;
                jobs[clientInfo.clientId]=schedule.scheduleJob(clientInfo.corn, function() {
                    publish(clientInfo.clientId,0,{
                        type:'start'
                    })
                });
            }
        }
    };

    /**
     * 返回任务列表
     */
    let getTaskItems=function(){
        return taskItems;
    };


    /**
     * 注册任务
     * @param taskInfo
     */
    let registerTask=function(taskInfo){
        taskInfo=JSON.parse(taskInfo);
        taskInfo.isOnline=1;
        taskInfo.taskServer=JSON.stringify( taskInfo.taskServer);
        delete taskInfo.data;
        taskItems[taskInfo.clientId]=taskInfo;
        redisClient.hmset(taskInfo.clientId,taskInfo);
        publish("Task:Monitor:TaskRegister",0,taskInfo);
        if(!jobs[taskInfo.clientId]){
            if(taskInfo.isAuto==="true"){
                jobs[taskInfo.clientId]=schedule.scheduleJob(taskInfo.corn, function() {
                    publish(taskInfo.clientId,0,{
                        type:'start'
                    })
                });
            }
        }
    };

    /**
     * 修改任务
     * @param taskInfo
     */
    let editTask=function(taskInfo){
        taskInfo=JSON.parse(taskInfo);
        taskInfo.taskServer=JSON.stringify( taskInfo.taskServer);
        delete taskInfo.data;
        taskItems[taskInfo.clientId]=taskInfo;
        redisClient.hmset(taskInfo.clientId,taskInfo);
        if(jobs[taskInfo.clientId]){
            if(taskInfo.isAuto==="true"){
                jobs[taskInfo.clientId]=schedule.scheduleJob(taskInfo.corn, function() {
                    publish(taskInfo.clientId,0,{
                        type:'start'
                    })
                });
            }else{
                jobs[taskInfo.clientId].cancel();
            }
        }
    };

    let startTask=function(taskInfo){
        publish(taskInfo.clientId,1,{
            type:'strart'
        });
    };

    let stopTask=function(taskInfo){
        publish(taskInfo.clientId,1,{
            type:'stop'
        });
    };

    /**
     * 收到消息
     * @param packet
     * @param client
     */
    let onReciveMsg=function (packet,client) {
        let topic = packet.topic;
        let payload=packet.payload.toString();
        switch (topic) {
            case "Task:Register":
                registerTask(payload);
                break;
            case "Task:Edit":
                editTask(payload);
                break;
            case "Task:Start":
                startTask(payload);
                break;
            case "Task:Stop":
                stopTask(payload);
                break;
            case "Task:MemoryInfo":
                console.log(payload);
                break;
        }


       // console.log('message-arrived--->', 'topic =' + topic + ',message = ' + packet.payload);
    };


    /**
     * 发布消息
     * @param topic
     * @param qos
     * @param payload
     */
    let publish=function (topic,qos=0,payload) {
        let message = {
            topic: topic,
            payload: JSON.stringify(payload), // or a Buffer
            qos: qos, // 0, 1, or 2
            retain: false // or true
        };
        Server.publish(message, ()=> {

        });
    };


    return{
        start:start,
        getTaskItems:getTaskItems,
        loadTaskItems:loadTaskItems,
        onReciveMsg:onReciveMsg,
        publish:publish
    }
};















